/**
 *
 */
package com.btkjgc.utils;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.jdbc.Work;
import org.hibernate.transform.Transformers;
import org.springframework.context.ApplicationContext;

/**
 * @author lzh
 * http://blog.csdn.net/loveyout/article/details/4193894
 */
final public class HibernateUtil
{
	private static SessionFactory sessionFactory = null;
	
	private static int BATCH_MAX_ROW=20;
 
	private HibernateUtil()
	{

		
	}
 

	public static void setSessionFactory(SessionFactory factory)
	{
		sessionFactory = factory;
	}

	public static SessionFactory getSessionFactory()
	{
		
		if(sessionFactory==null){
			ApplicationContext ac = ApplicationContextUtil.getApplicationContext();
			sessionFactory = (SessionFactory) ac.getBean("sessionFactory");
		}

		return sessionFactory;
	}

	public static Session openSession()
	{
 
		return getSessionFactory().openSession();
	}

	@SuppressWarnings("rawtypes")
	public static Object getObjectById(Class clazz, java.io.Serializable id)
	{
		Session session = null;
		Object object = null;
		try
		{
			session = openSession();
			object = session.get(clazz, id);
		}
		catch (Exception e)
		{
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}
		finally
		{
			if (session != null && session.isOpen())
			{
				session.close();
			}
		}
		return object;
	}

	public static <T> int batchSave(final T[] objs) {

		Session session = openSession();
		Transaction tx = session.beginTransaction();
		try {
			Integer[] keyArr= new Integer[objs.length];
			for (int i = 0; i < objs.length; i++) {

				keyArr[i]=(Integer) session.save(objs[i]);
				if (i % BATCH_MAX_ROW == 0) {
					session.flush();
					session.clear();
				}
			}
			
			session.flush();
			session.clear();
			tx.commit();
			return 1;
		} catch (Exception e) {
			e.printStackTrace();
			if (tx != null)
			{
				tx.rollback();
			}
			throw new RuntimeException(e.getMessage());
		
		} finally {
			if (session != null && session.isOpen()) {
				session.close();
			}
		}

	
	}

	public static Integer save(Object obj)
	{
		Session ss = null;
		Transaction tx = null;
		Integer key=  null;
		try
		{
			ss = openSession();
			tx = ss.beginTransaction();
		    key=  (Integer) ss.save(obj);
			tx.commit();
		}
		catch (Exception e)
		{
			e.printStackTrace();
			if (tx != null)
			{
				tx.rollback();
			}
			throw new RuntimeException(e.getMessage());
		}
		finally
		{
			if (ss != null && ss.isOpen())
			{
				ss.close();
			} 
		}
		return key;
	}
 
	public static void update(Object obj)
	{
		Session ss = null;
		Transaction tx = null;
		try
		{
			ss = openSession();
			tx = ss.beginTransaction();
			ss.update(obj);
			tx.commit();
		}
		catch (Exception e)
		{
			e.printStackTrace();
			if (tx != null)
			{
				tx.rollback();
			}
			throw new RuntimeException(e.getMessage());
		}
		finally
		{
			if (ss != null && ss.isOpen())
			{
				ss.close();
			}
		}
	}

	public static <T> int batchUpdate(final T[] objs) {

		Session session = openSession();
		Transaction tx = session.beginTransaction();
		try {
			for (int i = 0; i < objs.length; i++) {

				session.update(objs[i]);
				if (i % BATCH_MAX_ROW == 0) {
					session.flush();
					session.clear();
				}

			}
			session.flush();
			session.clear();
			tx.commit();
		} catch (Exception e) {
			e.printStackTrace();
			if (tx != null)
			{
				tx.rollback();
			}
			throw new RuntimeException(e.getMessage());
		} finally {
			if (session != null && session.isOpen()) {
				session.close();
			}
		}

		

		return objs.length;

	}
	
	public static void updateIfExists(Object obj)
	{
		Session ss = null;
		Transaction tx = null;
		try
		{
			ss = openSession();
			tx = ss.beginTransaction();
			ss.update(obj);
			tx.commit();
		}
		catch (Exception e)
		{
			if (tx != null)
			{
				tx.rollback();
			}
		}
		finally
		{
			if (ss != null && ss.isOpen())
			{
				ss.close();
			}
		}
	}

	public static void delete(Object obj)
	{
		Session ss = null;
		Transaction tx = null;
		try
		{
			ss = openSession();
			tx = ss.beginTransaction();
			ss.delete(obj);
			tx.commit();
		}
		catch (Exception e)
		{
			e.printStackTrace();
			if (tx != null)
			{
				tx.rollback();
			}
			throw new RuntimeException(e.getMessage());
		}
		finally
		{
			if (ss != null && ss.isOpen())
			{
				ss.close();
			}
		}
	}

	public static void saveOrUpdate(Object obj)
	{
		Session ss = null;
		Transaction tx = null;
		try
		{
			ss = openSession();
			tx = ss.beginTransaction();
			ss.saveOrUpdate(obj);
			tx.commit();
		}
		catch (Exception e)
		{
			e.printStackTrace();
			if (tx != null)
			{
				tx.rollback();
			}
			throw new RuntimeException(e.getMessage());
		}
		finally
		{
			if (ss != null && ss.isOpen())
			{
				ss.close();
			}
		}
	}

	@SuppressWarnings("rawtypes")
	public static List executeQueryList(String hql, Object... parameters)
	{
		Session session = null;
		List list = null;
		try
		{
			session = openSession();
			Query query = session.createQuery(hql);
			if (parameters != null && parameters.length > 0)
			{
				for (int i = 0; i < parameters.length; i++)
				{
					query.setString(i, parameters[i].toString());
				}
			}
			list = query.list();
		}
		catch (Exception e)
		{
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}
		finally
		{
			if (session != null && session.isOpen())
			{
				session.close();
			}
		}
		return list;
	}

	
	
	
	@SuppressWarnings("rawtypes")
	public static List executeQueryList(String hql,Class clazz,Object... parameters)
	{
		Session session = null;
		List list = null;
		try
		{
			session = openSession();
			Query query = session.createQuery(hql);
			if (parameters != null && parameters.length > 0)
			{
				for (int i = 0; i < parameters.length; i++)
				{
					query.setString(i, String.valueOf(parameters[i]));
				}
			}
			 list =query.setResultTransformer(Transformers.aliasToBean(clazz)).list();
		}
		catch (Exception e)
		{
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}
		finally
		{
			if (session != null && session.isOpen())
			{
				session.close();
			}
		}
		return list;
	}
	
 
	 
	
 

	public static int executeQueryCount(String hql,Object... parameters)
	{
		Session session = null;
		try
		{
			session = openSession();
			Query query = session.createQuery(hql);
			if (parameters != null && parameters.length > 0)
			{
				for (int i = 0; i < parameters.length; i++)
				{
					query.setString(i, parameters[i].toString());
				}
			}
			return ((Number) (query.uniqueResult())).intValue();
		}
		catch (Exception e)
		{
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}
		finally
		{
			if (session != null && session.isOpen())
			{
				session.close();
			}
		}
	}

	@SuppressWarnings("rawtypes")
	public static List executeQueryFinalNRecords(String hql,
			String[] parameters, Integer record_length)
	{
		Session session = null;
		List list = null;
		try
		{
			session = openSession();
			Query query = session.createQuery(hql);
			if (parameters != null && parameters.length > 0)
			{
				for (int i = 0; i < parameters.length; i++)
				{
					query.setString(i, parameters[i]);
				}
			}
			query.setMaxResults(record_length);
			list = query.list();
		}
		catch (Exception e)
		{
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}
		finally
		{
			if (session != null && session.isOpen())
			{
				session.close();
			}
		}
		return list;
	}
	public static void batchExecuteUpdate(List<String> hqlList)
	{
		Session ss = null;
		Transaction tx = null;
		try
		{
			ss = openSession();
			tx = ss.beginTransaction();
            for (int i = 0; i < hqlList.size(); i++) {
               	Query query = ss.createQuery(hqlList.get(i));
            	query.executeUpdate();
		    }
			tx.commit();
		}
		catch (Exception e)
		{
			e.printStackTrace();
			if (tx != null)
			{
				tx.rollback();
			}
			throw new RuntimeException(e.getMessage());
		}
		finally
		{
			if (ss != null && ss.isOpen())
			{
				ss.close();
			}
		}
	}

	
	public static void batchExecuteUpdate(List<String> hqlList,List<List<String>> paramLists)
	{
		Session ss = null;
		Transaction tx = null;
		try
		{
			ss = openSession();
			tx = ss.beginTransaction();
            for (int i = 0; i < hqlList.size(); i++) {
               	Query query = ss.createQuery(hqlList.get(i));
                List<String> paramLists2= paramLists.get(i);
               	for (int j = 0; j <paramLists2.size(); j++) {
               		query.setString(j,paramLists2.get(j));
				}
            	query.executeUpdate();
		    }
			tx.commit();
		}
		catch (Exception e)
		{
			e.printStackTrace();
			if (tx != null)
			{
				tx.rollback();
			}
			throw new RuntimeException(e.getMessage());
		}
		finally
		{
			if (ss != null && ss.isOpen())
			{
				ss.close();
			}
		}
	}

	
	public static void executeUpdate(String hql, String... parameters)
	{
		Session ss = null;
		Transaction tx = null;
		try
		{
			ss = openSession();
			tx = ss.beginTransaction();
			Query query = ss.createQuery(hql);
			if (parameters != null && parameters.length > 0)
			{
				for (int i = 0; i < parameters.length; i++)
				{
					query.setString(i, parameters[i]);
				}
			}
			query.executeUpdate();
			tx.commit();
		}
		catch (Exception e)
		{
			e.printStackTrace();
			if (tx != null)
			{
				tx.rollback();
			}
			throw new RuntimeException(e.getMessage());
		}
		finally
		{
			if (ss != null && ss.isOpen())
			{
				ss.close();
			}
		}
	}

	
	public static void batchExecuteSQLUpdate(List<String>sqlList)
	{
		Session ss = null;
		Transaction tx = null;
		try
		{
			ss = openSession();
			tx = ss.beginTransaction();
			for (int i = 0; i < sqlList.size(); i++) {
				Query query = ss.createSQLQuery(sqlList.get(i));
				query.executeUpdate();
			}
			
			tx.commit();
		}
		catch (Exception e)
		{
			e.printStackTrace();
			if (tx != null)
			{
				tx.rollback();
			}
			throw new RuntimeException(e.getMessage());
		}
		finally
		{
			if (ss != null && ss.isOpen())
			{
				ss.close();
			}
		}
	}
	
	public static void executeSQLUpdate(String sql, Object... parameters)
	{
		Session ss = null;
		Transaction tx = null;
		try
		{
			ss = openSession();
			tx = ss.beginTransaction();
			Query query = ss.createSQLQuery(sql);
			if (parameters != null && parameters.length > 0)
			{
				for (int i = 0; i < parameters.length; i++)
				{
					if (parameters[i] != null)
					{
						query.setString(i, parameters[i].toString());
					}
					else
					{
						query.setString(i, null);
					}
				}
			}
			query.executeUpdate();
			tx.commit();
		}
		catch (Exception e)
		{
			e.printStackTrace();
			if (tx != null)
			{
				tx.rollback();
			}
			throw new RuntimeException(e.getMessage());
		}
		finally
		{
			if (ss != null && ss.isOpen())
			{
				ss.close();
			}
		}
	}

	public static int executeUpdateIfExist(String hql, String[] parameters)
	{
		Session ss = null;
		Transaction tx = null;
		int updateNumbers = 0;
		try
		{
			ss = openSession();
			tx = ss.beginTransaction();
			Query query = ss.createQuery(hql);
			if (parameters != null && parameters.length > 0)
			{
				for (int i = 0; i < parameters.length; i++)
				{
					query.setString(i, parameters[i]);
				}
			}
			updateNumbers = query.executeUpdate();
			tx.commit();
		}
		catch (Exception e)
		{
			e.printStackTrace();
			if (tx != null)
			{
				tx.rollback();
			}
			throw new RuntimeException(e.getMessage());
		}
		finally
		{
			if (ss != null && ss.isOpen())
			{
				ss.close();
			}
		}
		return updateNumbers;
	}

	public static Object  executeQueryOneObject(String hql, String...parameters)
	{
		Session ss = null;
		Object obj = null;
		try
		{
			ss = openSession();
			Query query = ss.createQuery(hql);

			if (parameters != null && parameters.length > 0)
			{
				for (int i = 0; i < parameters.length; i++)
				{
					query.setString(i, parameters[i]);
				}
			}
			obj = query.uniqueResult();
		}
		catch (Exception e)
		{
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}
		finally
		{
			if (ss != null && ss.isOpen())
			{
				ss.close();
			}
		}
		return obj;
	}
 

	@SuppressWarnings({ "unused", "rawtypes" })
	public List findColumnByPage(String hql, String parameters[])
	{
		// Creat by Rong on 2015-8-8
		Session session = null;
		List list = null;
		try
		{
			session = HibernateUtil.openSession();
			Query query = session.createQuery(hql);
			if (parameters != null && parameters.length > 0)
			{
				for (int i = 0; i < parameters.length; i++)
				{
					query.setString(i, parameters[i]);
				}
			}
			query.setFirstResult(0);
			query.setMaxResults(1);
			return query.list();
		}
		catch (Exception e)
		{
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}
		finally
		{
			if (session != null && session.isOpen())
			{
				session.close();
			}
		}
	}

	@SuppressWarnings("rawtypes")
	public static List executeQueryList(String hql, int pageIndex, int pageSize,
			String[] parameters)
	{
		Session session = null;
		List list = null;
		try
		{
			session = openSession();
			Query query = session.createQuery(hql);
			query.setFirstResult(pageIndex * pageSize);
			query.setMaxResults(pageSize);
			if (parameters != null && parameters.length > 0)
			{
				for (int i = 0; i < parameters.length; i++)
				{
					query.setString(i, parameters[i]);
				}
			}
			list = query.list();
		}
		catch (Exception e)
		{
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}
		finally
		{
			if (session != null && session.isOpen())
			{
				session.close();
			}
		}
		return list;
	}
	
	 
	
	public static Integer executeSQLUpdate(String sql)
	{
		// 直接执行sql，直接执行在数据库可以执行的sql（相当于不使用映射文件）
		Session session = null;
		Transaction tx = null;
		int updateNumbers = 0;
		try
		{
			session = openSession();
			tx = session.beginTransaction();
			Query query = session.createSQLQuery(sql);
			updateNumbers=query.executeUpdate();
			tx.commit();
			
			return updateNumbers;
		}
		catch (Exception e)
		{
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}
		finally
		{
			if (session != null && session.isOpen())
			{
				session.close();
			}
		}
	}

	@SuppressWarnings("rawtypes")
	public static List executeSQLQueryList(String sql)
	{
		Session session = null;
		List list = null;
		try
		{
			session = HibernateUtil.openSession();
			Query query = session.createSQLQuery(sql);
			/*
			 * if (parameters != null && parameters.length > 0) { for (int i =
			 * 0; i < parameters.length; i++) { query.setString(i,
			 * parameters[i]); } }
			 */
			list =query.list();
			return list;
		}
		catch (Exception e)
		{
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}
		finally
		{
			if (session != null && session.isOpen())
			{
				session.close();
			}
		}
	}
	
 
	@SuppressWarnings("rawtypes")
	public static List executeSQLQueryList(String sql, Class clazz,Object... parameters)
	{
		Session session = null;
	    List  list = null;
		try
		{
			session = openSession();
			SQLQuery query = session.createSQLQuery(sql);
			 
			if (parameters != null && parameters.length > 0)
			{
				for (int i = 0; i < parameters.length; i++)
				{
					query.setString(i, parameters[i].toString());
				}
			}
			 list =query.setResultTransformer(Transformers.aliasToBean(clazz)).list();
		}
		catch (Exception e)
		{
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}
		finally
		{
			if (session != null && session.isOpen())
			{
				session.close();
			}
		}
		return list;
	}
	
	
	@SuppressWarnings("rawtypes")
	public static Object executeSQLQueryObject(String sql, Class clazz,Object... parameters)
	{
		Session session = null;
	    List  list = null;
	    Object object= null;
		try
		{
			session = openSession();
			SQLQuery query = session.createSQLQuery(sql);
			 
			if (parameters != null && parameters.length > 0)
			{
				for (int i = 0; i < parameters.length; i++)
				{
					query.setString(i, parameters[i].toString());
				}
			}
			 list =query.setResultTransformer(Transformers.aliasToBean(clazz)).list();
             if(list!=null && list.size()!=0){
            	 object=list.get(0);
             }
		}
		catch (Exception e)
		{
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}
		finally
		{
			if (session != null && session.isOpen())
			{
				session.close();
			}
		}
		return  object;
	}
 
	
	@SuppressWarnings("rawtypes")
	public static Object executeSQLQueryObject(String sql,Object... parameters)
	{
		Session session = null;
	    List  list = null;
	    Object object= null;
		try
		{
			session = openSession();
			SQLQuery query = session.createSQLQuery(sql);
			 
			if (parameters != null && parameters.length > 0)
			{
				for (int i = 0; i < parameters.length; i++)
				{
					query.setString(i, parameters[i].toString());
				}
			}
			 list =query.list();
             if(list!=null && list.size()!=0){
            	 object=list.get(0);
             }
		}
		catch (Exception e)
		{
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}
		finally
		{
			if (session != null && session.isOpen())
			{
				session.close();
			}
		}
		return  object;
	}
 
	
	public static int executeSQLQueryInt(String sql, Object... parameters)
	{
		Session session = null;
		try
		{
			session = openSession();
			Query query = session.createSQLQuery(sql);
			if (parameters != null && parameters.length > 0)
			{
				for (int i = 0; i < parameters.length; i++)
				{
					query.setString(i, parameters[i].toString());
				}
			}
			return ((Number) (query.uniqueResult())).intValue();
		}
		catch (Exception e)
		{
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}
		finally
		{
			if (session != null && session.isOpen())
			{
				session.close();
			}
		}
	}

	
	@SuppressWarnings("rawtypes")
	public static List executeSQLQueryList(String sql, int pageIndex, int pageSize,
			Object[] parameters,Class clazz)
	{
		Session session = null;
		List list = null;
		try
		{
			session = openSession();
			Query query = session.createSQLQuery(sql);
			query.setFirstResult(pageIndex * pageSize);
			query.setMaxResults(pageSize);
			if (parameters != null && parameters.length > 0)
			{
				for (int i = 0; i < parameters.length; i++)
				{
					query.setString(i, parameters[i].toString());
				}
			}
			 list =query.setResultTransformer(Transformers.aliasToBean(clazz)).list();
		}
		catch (Exception e)
		{
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}
		finally
		{
			if (session != null && session.isOpen())
			{
				session.close();
			}
		}
		return list;
	}
	
	public static void callProcedure(final String procedure,final Object... objs){
		
		Session session = null;
		try
		{
			session = openSession();
			Transaction tx = session.beginTransaction();
	 
			session.doWork(new Work() {
				public void execute(Connection connection) {
					// 这里已经得到connection了，可以继续你的JDBC代码。
					// 注意不要close了这个connection。
					CallableStatement cstmt;
					try {
						cstmt = connection.prepareCall(procedure);
						for (int i = 0; i < objs.length; i++) {
							cstmt.setObject(i, objs[i]);
						}
						cstmt.executeUpdate();
					} catch (SQLException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
		
				}
			});
			tx.commit();  
		}
		catch (Exception e)
		{
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}
		finally
		{
			if (session != null && session.isOpen())
			{
				session.close();
			}
		}
	
	}

}
